#include <iostream>
#include <sw/redis++/redis++.h>
#include <vector>
#include <string>
#include "PPrint.hpp"
#include <chrono>
#include <set>

using std::cout;
using std::endl;
using std::string;
using std::unordered_map;
using std::vector;

using std::set;
using sw::redis::Redis;
using namespace std::chrono_literals;

void test1(Redis &redis)
{
    cout << "hset and hget" << endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", std::make_pair("f2", "222"));
    redis.hset("key",
               {std::make_pair("f3", "333"),
                std::make_pair("f4", "444")});
    vector<std::pair<string, string>> fields = {
        {std::make_pair("f5", "555"),
         std::make_pair("f6", "666")}};
    redis.hset("key", fields.begin(), fields.end());

    auto result = redis.hget("key", "f1");
    if (result)
        cout << result.value() << endl;
    else
        cout << "result failed!!!" << endl;
}

void test2(Redis &redis)
{
    cout << "hset and hget" << endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");

    bool result = redis.hexists("key", "f4");
    cout << result << endl;
    result = redis.hexists("key", "f3");
    cout << result << endl;
}

void test3(Redis &redis)
{
    cout << "hset and hget" << endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");
    redis.hset("key", "f4", "444");
    redis.hset("key", "f5", "555");

    auto result = redis.hdel("key", "f1"); // del return the deleted count
    cout << result << endl;

    result = redis.hdel("key", {"f2", "f3"});
    cout << result << endl;

    auto len = redis.hlen("key");
    cout << len << endl;
}

void test4(Redis &redis)
{
    cout << "hset and hget" << endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");

    vector<string> fields;
    auto itFields = std::back_inserter(fields);
    redis.hkeys("key", itFields);
    printContainer(fields);

    vector<string> values;
    auto itValues = std::back_inserter(values);
    redis.hvals("key", itValues);
    printContainer(values);
}

void test5(Redis &redis)
{
    cout << "hmset and hmget" << endl;
    redis.flushall();

    redis.hmset("key", {std::make_pair("f1", "111"),
                        std::make_pair("f2", "222"),
                        std::make_pair("f3", "333")});

    vector<std::pair<string, string>> pairs = {
        {std::make_pair("f4", "555"),
         std::make_pair("f5", "666"),
         std::make_pair("f6", "777")}};

    redis.hmset("key", pairs.begin(), pairs.end());

    vector<string> values;
    auto it = std::back_inserter(values);
    redis.hmget("key", {"f1", "f2", "f3"}, it);
    printContainer(values);
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    test5(redis);
}